// ============================== 导入依赖 ============================== //

// 插件配置
const getNow = () => {
  const [now, trans] = [new Date(), (x) => `0${x}`.slice(-2)]
  const [y, M, d, h, m] = [now.getYear(), now.getMonth() + 1, now.getDate(), now.getHours(), now.getMinutes()]
  return `${trans(y)}${trans(M)}${trans(d)}${trans(h)}${trans(m)}`
}
const webpack = require('webpack')
const PLUGINS = [
  new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /en-gb|zh-cn/), // 忽略其它语言文件
  new webpack.DefinePlugin({ // 定义通用环境变量
    'process.env.HASH': 230815, // CDN 文件的 HASH 值
    'process.env.CORE_VERSION': getNow(), // 内核版本
    'process.env.GAODE_CODE': JSON.stringify('09b00e6aa4b74861e0aa4a913e6d3570'), // 高德地图安全代号
    'process.env.GAODE_KEY': JSON.stringify('59bbb966f420ad2e3ed368589c8b5706'), // 高德地图安全标识
  }),
]

// 别名配置
const alias = (path) => require('path').resolve(__dirname, path)
const ALIAS = {
  '@root': alias('./'), // 根目录 (本 WEBPACk.js 所在目录)

  '@api': alias('./【API】/js'), // 接口目录

  '@demo': alias('./demo/src'), // 示例页
  '@login': alias('./login/src'), // 登录页
  '@print': alias('./print/src'), // 打印页
  '@model': alias('./model/src'), // 模型页
  '@screen': alias('./screen/src'), // 大屏页
  '@questionnaire': alias('./questionnaire/src'), // 问卷页

  '@admin': alias('./admin/src'), // 标准版
  '@cnzy': alias('./标准版/苍南中医/src'), // 苍南中医

  '@af_admin': alias('./af_admin/src'), // 安防版
  '@af_lgyy': alias('./安防版/龙港医院/src'), // 龙港医院

  '@kj_admin': alias('./kj_admin/src'), // 科技版

  '@iframe': alias('./iframe/src'), // 内嵌版
}

// CDN 配置
const CDN = {
  axios: 'axios',
  dayjs: 'dayjs',
  superagent: 'superagent',

  vue: 'Vue',
  vuex: 'Vuex',
  'vue-router': 'VueRouter',

  'element-ui': 'ELEMENT', // 必须全大写
  echarts: 'echarts',
  jsencrypt: 'JSEncrypt',
}

// HASH 配置
const hash = (type, ext) => `${type}/[name].${ext || type}?[contenthash:6]`
const HASH = {
  JS: { filename: hash('js'), chunkFilename: hash('js') },
  CSS: { filename: hash('css'), chunkFilename: hash('css'), ignoreOrder: true },
  IMG: { name: hash('img', '[ext]') },
}

// 分片配置
const SPLIT = {
  cacheGroups: {
    CORE: { name: 'CORE', priority: 90, chunks: 'all', test: /CORE/, enforce: true },
    components: { name: 'components', priority: 80, chunks: 'async', test: /components/, enforce: true },
    babylon: { name: 'babylon', priority: 30, test: /babylonjs/ },
    vendors: { name: 'chunk-vendors', priority: 20, test: /node_modules/ },
    repeat: { name: 'chunk-repeat', priority: 10, chunks: 'all', minChunks: 2, reuseExistingChunk: true },
  },
}

// 调试配置
const DEBUG = {
  // 分离源码
  devtoolModuleFilenameTemplate: (info) => {
    // 真正源文件的 allLoaders 为空，且不包括 require.context() 生成的文件
    const realSrc = !info.allLoaders && !/ sync .+/.test(info.resource)
    if (realSrc) return `webpack:///${info.resource.replace(/^(\.\/)?src/, '源码')}`
    return `webpack:///${info.resourcePath}?${info.hash}`
  },
}

// 是否为生产环境
const IS_PROD = process.env.NODE_ENV === 'production'

// ============================== 导出配置 ============================== //

module.exports = {
  // —————————————————————————————— 对象配置 —————————————————————————————— //

  configureWebpack: {
    resolve: { alias: ALIAS }, // 别名配置
    externals: CDN, // CDN 配置
    devtool: IS_PROD ? 'none' : 'module-eval-source-map', // 调试模式 (见末尾说明)
    output: IS_PROD ? HASH.JS : DEBUG, // 输出配置
    optimization: { splitChunks: SPLIT }, // 分片配置
    plugins: PLUGINS, // 插件配置
  },

  // —————————————————————————————— 链式配置 —————————————————————————————— //

  chainWebpack: (config) => {
    // CSS 配置，等同于 vue-cli 的配置 css: { extract: CSS_HASH }
    IS_PROD && config.plugin('extract-css').tap(() => [HASH.CSS])

    // 图片配置
    config.module.rule('images').use('url-loader').loader('url-loader').tap((options) => {
      Object.assign(options.fallback.options, HASH.IMG)
      return options
    })
  },
}

// 调试模式
// 使用 cheap 模式可以大幅提高souremap 生成的效率，但组合 cheap-module-eval-source-map 会丢失文件路径信息。
// 使用 eval 方式可大幅提高持续构建效率。官方文档提供的速度对比表格可以看到 eval 模式的编译速度很快。
// 使用 module 可支持babel这种预编译工具（在 webpack 里做为 loader 使用）。
// 使用 eval-source-map 模式可以减少网络请求。这会略微提高点效率。而生产环境中则不宜用 eval，这样会让文件变得极大。
